setState是同步还是异步 | 您所在的位置:网站首页 › settimeout setstate › setState是同步还是异步 |
在讨论这个问题之前,先看一个问题 setState执行后打印state是更新前的还是更新后的? 合成事件中 更新之前的值 class App extends React.Component { state = { count: 0 } handleClick = () => { this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之前的值 } render() { return ( 点击 ) } } 复制代码 钩子函数中 更新之前的值 class App extends React.Component { state = { count: 0 } componentDidMount() { this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之前的值 } render() { return null } } 复制代码 原生事件中 更新之后的值 class App extends React.Component { state = { count: 0 } handleClick = () => { this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之后的值 } componentDidMount() { document.body.addEventerListener("click", this.handleCLick) } render() { return ... } } 复制代码 setTimeout中 更新之后的值 class App extends React.Component { state = { count: 0 } handleClick = () => { setTimeout(() =>{ this.setState({ count: this.state.count + 1 }) console.info(this.state); // 是更新之后的值 }) } render() { return ( 点击 ) } } 复制代码 结论从上面的例子可以看出 在合成事件和生命周期中是"异步"的 在原生事件和setTimeout中是同步的但是,这里说的异步真的是异步吗?那么就用setState和异步事件做比较,看下打印顺序 setState和异步做比较 包含在setTimeout中和异步做比较 handleClick = () => { setTimeout(() => { console.log('宏任务触发') }) Promise.resolve().then(() => { console.log('微任务触发') }) setTimeout(() => { this.setState({ count: this.state.count + 1 }, () => { console.log('setState变化') }) }) } 复制代码打印顺序: 微任务触发 -> 宏任务触发 -> setState变化 setState直接和异步做比较 handleClick = () => { setTimeout(() => { console.log('宏任务触发') }) Promise.resolve().then(() => { console.log('微任务触发') }) this.setState({ count: this.state.count + 1 }, () => { console.log('setState变化') }) } 复制代码打印顺序:setState变化 -> 微任务触发 -> 宏任务触发 由此可见:setState不是一个异步的任务,只是一个被延迟执行的同步函数 总结setState是一个伪异步,或者可以称为defer,即延迟执行但本身还在一个事件循环,所以它的执行顺序在同步代码后、异步代码前。为什么会有这种现象?这就要说到react的合成事件了,react的批处理更新也得益于合成事件 |
今日新闻 |
推荐新闻 |
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 |